package com.lightsh.widget;

import com.lightsh.widget.animation.Rotate3dAnimation;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import android.widget.LinearLayout;

/**
 * 该类用来实现layout之间的3d动画切换。
 * 注意：如果动画时出现残影，请尝试使用match_parent(fill_parent)设置该布局的高宽属性。该类继承自{@link FrameLayout}。
 * @author Shu
 *
 */
public class Rotate3dLayout extends FrameLayout{
	
	private static final boolean DEBUG = false;
	private static final String TAG = "Rotate3dLayout";
	private View[] mViews;
	
	
	
	private boolean mbAnimating = false;
	
	
	public Rotate3dLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
		setPersistentDrawingCache(ViewGroup.PERSISTENT_ANIMATION_CACHE);
	}
	
	public Rotate3dLayout(Context context){
		this(context, null);
	}
	
	/**
	 * 进行动画切换
	 * @param toChild 目标的视图
	 * @return 如果动画切换成功，返回true，否则返回false。注意，如果前面的动画未结束，该方法也返回false。
	 *     		当返回false时，视图不会切换.
	 */
	public boolean startRotate(int toChild, boolean bLeftToRight){
		if(toChild >= mViews.length || mbAnimating){
			return false;
		}
		float centerX = getWidth() / 2.0f;
		float centerY = getHeight() / 2.02f;
		Rotate3dAnimation rotation = new Rotate3dAnimation(getFromDegress1(bLeftToRight), getToDegress1(bLeftToRight), centerX, centerY, mDepthZ, false);
		rotation.setDuration(DURATION / 2);
        rotation.setInterpolator(mFirstInterpolator);
        rotation.setAnimationListener(new DisplayNextView(toChild, bLeftToRight));
        Rotate3dLayout.this.startAnimation(rotation);
        return true;
	}
	
	@Override
	protected void onAttachedToWindow() {
		super.onAttachedToWindow();
		int count = getChildCount();
		if(count < 2){
			throw new RuntimeException("Rotate3dLayout need at least 2 direct child!");
		}
		mViews = new View[count];
		for(int i = 0; i < count; ++i){
			mViews[i] = getChildAt(i);
		}
		
		log("chile count:" + count);
	}
	private void log(String msg){
		if(DEBUG){
			Log.e(TAG, msg);
		}
	}

	private float mDepthZ = 500.0f;
	/**
	 * 设置旋转时，视图项Z轴移动的深度(即缩小视图的比例值)
	 * 默认值为500.0f
	 * @param depthZ
	 */
	public void setDepthZ(float depthZ){
		mDepthZ = depthZ;
	}
	
	private Interpolator mFirstInterpolator = new AccelerateInterpolator(2f);
	private Interpolator mSecondInterpolator = new DecelerateInterpolator(2f);
	
	/**
	 * 设置动画的变化率
	 * @param first		前半部分的变化率
	 * @param second	后半部分的变化率
	 */
	public void setInterpolator(Interpolator first, Interpolator second){
		mFirstInterpolator = first;
		mSecondInterpolator = second;
	}
	
	private static final int DURATION = 1000;
	private int getFromDegress1(boolean bReverse){
		if(bReverse){
			return 0;
		}else{
			return 0;
		}
	}
	private int getToDegress1(boolean bReverse){
		if(bReverse){
			return -90;
		}else{
			return 90;
		}
	}
	private int getFromDegress2(boolean bReverse){
		if(bReverse){
			return 90;
		}else{
			return -90;
		}
	}
	private int getToDegress2(boolean bReverse){
		if(bReverse){
			return 0;
		}else{
			return 0;
		}
	}
	
	/**
     * 监听动画，在动画进行到一半时进行切换。
     */
    private final class DisplayNextView implements Animation.AnimationListener {
    	private final int mToChild;
    	private final boolean mbReverse;
        private DisplayNextView(int toChild, boolean bReverse) {
        	mToChild = toChild;
        	mbReverse = bReverse;
        }

        public void onAnimationStart(Animation animation) {
        	mbAnimating = true;
        }

        public void onAnimationEnd(Animation animation) {
            Rotate3dLayout.this.post(new SwapViews(mToChild, mbReverse));
        }

        public void onAnimationRepeat(Animation animation) {
        }
    }
    
    /**
     * 在动画进行到一半时，进行视图的切换和后续动画的实现
     */
    private final class SwapViews implements Runnable {
        private final int mToChild;
        private final boolean mbReverse;

        public SwapViews(int toChild, boolean bReverse) {
            mToChild = toChild;
            mbReverse = bReverse;
        }

        public void run() {
            final float centerX = getWidth() / 2.0f;
            final float centerY = getHeight() / 2.0f;
            for(View view : mViews){
            	if(view.getVisibility() == View.VISIBLE){
            		view.setVisibility(View.GONE);
            	}
            }
            mViews[mToChild].setVisibility(View.VISIBLE);
            mViews[mToChild].requestFocus();
            
            Rotate3dAnimation rotation = new Rotate3dAnimation(getFromDegress2(mbReverse), getToDegress2(mbReverse), centerX, centerY, mDepthZ, true);
            rotation.setDuration(DURATION / 2);
            rotation.setInterpolator(mSecondInterpolator);
            rotation.setAnimationListener(new Animation.AnimationListener() {
				
				public void onAnimationStart(Animation animation) {
					
				}
				
				public void onAnimationRepeat(Animation animation) {
					
				}
				
				public void onAnimationEnd(Animation animation) {
					mbAnimating = false;
					
				}
			});
            Rotate3dLayout.this.startAnimation(rotation);
        }
    }
}
